package com.hmall.gateway.routers;

import cn.hutool.json.JSONUtil;
import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import javax.annotation.PostConstruct;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Executor;

@Slf4j
@Component
@RequiredArgsConstructor
public class DynamicRouteLoader {
    private final NacosConfigManager nacosConfigManager;
    private final String dataId="gateway-routes.json";
    private final String group="DEFAULT_GROUP";
    private final RouteDefinitionWriter writer;
    private final Set<String> routeIds =new HashSet<>();
    @PostConstruct
    public void intRoutesConfigLigListener() throws NacosException {

        log.info("监听动态路由配置文件");
        //1.项目启动时，先拉取一次配置，并且添加配置监听器
        String configInfo = nacosConfigManager.getConfigService()
                .getConfigAndSignListener(dataId, group, 5000, new Listener() {
            @Override
            public Executor getExecutor() {
                return null;
            }

            @Override
            public void receiveConfigInfo(String configInfo) {
                //2.监听到配置文件有更新，则重新加载路由
                updateConfigInfo(configInfo);
            }
        });
        //第一次读取到配置也需要重新加载路由
        updateConfigInfo(configInfo);
    }
    public void updateConfigInfo(String configInfo){
        log.info("更新动态路由配置:{}", configInfo);
        //1.解析配置信息，转RouteDefinition
        List<RouteDefinition> routeDefinitions = JSONUtil.toList(configInfo, RouteDefinition.class);
        //2.1删除所有路由
         for (String routeId : routeIds){
             writer.delete(Mono.just(routeId)).subscribe();
         }
        //2.2更新路由
        for (RouteDefinition routeDefinition : routeDefinitions){
            //2.3保存路由
            writer.save(Mono.just(routeDefinition)).subscribe();
            //2.4记录路由
            routeIds .add(routeDefinition.getId());
        }
    }
}
